{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://course.rs/advance/global-variable.html\n",
    "\n",
    "**TL;DR**\n",
    "\n",
    "- 全局变量不一定要用 `static` 声明，但它们的生命周期都是 `'static`。\n",
    "- **编译期初始化**：\n",
    "  - `const`：不可变、需显式类型、常量表达式赋值，常用于全局配置。\n",
    "  - `static`：全局单实例，需 `unsafe` 访问，值必须实现 `Sync`，也只能用常量表达式初始化。\n",
    "  - 原子类型（如 `AtomicUsize`）：提供线程安全的全局状态修改。\n",
    "- **运行期初始化**：\n",
    "  - `lazy_static!`：宏实现懒初始化，访问时有少量性能开销。\n",
    "  - `Box::leak`：将堆分配数据“泄漏”为 `'static` 生命周期，适合全局动态配置。\n",
    "  - 标准库懒加载容器（`OnceCell` / `OnceLock` / `LazyCell` / `LazyLock`）：无需依赖外部宏，支持单次或按需初始化，区分单线程与多线程版。\n",
    "- 选择策略：编译期已知值用 `const` / `static` / 原子类型；需运行期初始化或复杂构造时，使用惰性初始化工具（`lazy_static!`、`OnceLock`、`LazyLock`、`Box::leak` 等）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在一些场景，我们可能需要全局变量来简化状态共享的代码，包括全局 ID，全局数据存储等等，下面一起来看看有哪些创建全局变量的方法。\n",
    "\n",
    "首先，有一点可以肯定，全局变量的生命周期肯定是`'static`，但是不代表它需要用`static`来声明，例如常量、字符串字面值等无需使用`static`进行声明，原因是它们已经被打包到二进制可执行文件中。\n",
    "\n",
    "下面我们从编译期初始化及运行期初始化两个类别来介绍下全局变量有哪些类型及该如何使用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [编译期初始化](https://course.rs/advance/global-variable.html#编译期初始化)\n",
    "\n",
    "我们大多数使用的全局变量都只需要在编译期初始化即可，例如静态配置、计数器、状态值等等。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [静态常量](https://course.rs/advance/global-variable.html#静态常量)\n",
    "\n",
    "全局常量可以在程序任何一部分使用，当然，如果它是定义在某个模块中，你需要引入对应的模块才能使用。常量，顾名思义它是不可变的，很适合用作静态配置："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户ID允许的最大值是9223372036854775807\n"
     ]
    }
   ],
   "source": [
    "const MAX_ID: usize =  usize::MAX / 2;\n",
    "\n",
    "fn main() {\n",
    "   println!(\"用户ID允许的最大值是{}\",MAX_ID);\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**常量与普通变量的区别**\n",
    "\n",
    "- 关键字是`const`而不是`let`\n",
    "- 定义常量必须指明类型（如 i32）不能省略\n",
    "- 定义常量时变量的命名规则一般是全部大写\n",
    "- 常量可以在任意作用域进行定义，其生命周期贯穿整个程序的生命周期。编译时编译器会尽可能将其内联到代码中，所以在不同地方对同一常量的引用并不能保证引用到相同的内存地址\n",
    "- 常量的赋值只能是常量表达式/数学表达式，也就是说必须是在编译期就能计算出的值，如果需要在运行时才能得出结果的值比如函数，则不能赋值给常量表达式\n",
    "- 对于变量出现重复的定义(绑定)会发生变量遮盖，后面定义的变量会遮住前面定义的变量，常量则不允许出现重复的定义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [静态变量](https://course.rs/advance/global-variable.html#静态变量)\n",
    "\n",
    "静态变量允许声明一个全局的变量，常用于全局数据统计，例如我们希望用一个变量来统计程序当前的总请求数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "creating a shared reference to mutable static",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[static_mut_refs] Error:\u001b[0m creating a shared reference to mutable static",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_3:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m6 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mq\u001b[0m\u001b[38;5;249m!\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;54mR\u001b[0m\u001b[38;5;54mE\u001b[0m\u001b[38;5;54mQ\u001b[0m\u001b[38;5;54mU\u001b[0m\u001b[38;5;54mE\u001b[0m\u001b[38;5;54mS\u001b[0m\u001b[38;5;54mT\u001b[0m\u001b[38;5;54m_\u001b[0m\u001b[38;5;54mR\u001b[0m\u001b[38;5;54mE\u001b[0m\u001b[38;5;54mC\u001b[0m\u001b[38;5;54mV\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m1\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                    \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m                          \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m shared reference to mutable static",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "static mut REQUEST_RECV: usize = 0;\n",
    "\n",
    "fn main() {\n",
    "   unsafe {\n",
    "        REQUEST_RECV += 1;\n",
    "        assert_eq!(REQUEST_RECV, 1);\n",
    "   }\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [],
   "source": [
    "use std::cell::UnsafeCell;\n",
    "\n",
    "struct Counter(UnsafeCell<usize>);\n",
    "unsafe impl Sync for Counter {} // 你来保证并发安全\n",
    "\n",
    "static REQUEST_RECV: Counter = Counter(UnsafeCell::new(0));\n",
    "\n",
    "fn main() {\n",
    "    unsafe {\n",
    "        *REQUEST_RECV.0.get() += 1;\n",
    "        assert_eq!(*REQUEST_RECV.0.get(), 1);\n",
    "    }\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Rust 要求必须使用`unsafe`语句块才能访问和修改`static`变量，因为这种使用方式往往并不安全，其实编译器是对的，当在多线程中同时去修改时，会不可避免的遇到脏数据。\n",
    "\n",
    "只有在同一线程内或者不在乎数据的准确性时，才应该使用全局静态变量。\n",
    "\n",
    "和常量相同，定义静态变量的时候必须赋值为在编译期就可以计算出的值(常量表达式/数学表达式)，不能是运行时才能计算出的值(如函数)\n",
    "\n",
    "**静态变量和常量的区别**\n",
    "\n",
    "- 静态变量不会被内联，在整个程序中，静态变量只有一个实例，所有的引用都会指向同一个地址\n",
    "- 存储在静态变量中的值必须要实现 Sync trait"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [原子类型](https://course.rs/advance/global-variable.html#原子类型)\n",
    "\n",
    "想要全局计数器、状态控制等功能，又想要线程安全的实现，原子类型是非常好的办法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当前用户请求数100\n"
     ]
    }
   ],
   "source": [
    "use std::sync::atomic::{AtomicUsize, Ordering};\n",
    "\n",
    "static REQUEST_RECV: AtomicUsize  = AtomicUsize::new(0);\n",
    "\n",
    "fn main() {\n",
    "    for _ in 0..100 {\n",
    "        REQUEST_RECV.fetch_add(1, Ordering::Relaxed);\n",
    "    }\n",
    "\n",
    "    println!(\"当前用户请求数{:?}\",REQUEST_RECV);\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [示例：全局 ID 生成器](https://course.rs/advance/global-variable.html#示例全局-id-生成器)\n",
    "\n",
    "来看看如何使用上面的内容实现一个全局 ID 生成器:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [],
   "source": [
    "use std::sync::atomic::{Ordering, AtomicUsize};\n",
    "\n",
    "struct Factory{\n",
    "    factory_id: usize,\n",
    "}\n",
    "\n",
    "static GLOBAL_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);\n",
    "const MAX_ID: usize = usize::MAX / 2;\n",
    "\n",
    "fn generate_id()->usize{\n",
    "    // 检查两次溢出，否则直接加一可能导致溢出\n",
    "    let current_val = GLOBAL_ID_COUNTER.load(Ordering::Relaxed);\n",
    "    if current_val > MAX_ID{\n",
    "        panic!(\"Factory ids overflowed\");\n",
    "    }\n",
    "    GLOBAL_ID_COUNTER.fetch_add(1, Ordering::Relaxed);\n",
    "    let next_id = GLOBAL_ID_COUNTER.load(Ordering::Relaxed);\n",
    "    if next_id > MAX_ID{\n",
    "        panic!(\"Factory ids overflowed\");\n",
    "    }\n",
    "    next_id\n",
    "}\n",
    "\n",
    "impl Factory{\n",
    "    fn new()->Self{\n",
    "        Self{\n",
    "            factory_id: generate_id()\n",
    "        }\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "关于原子类型的讲解看[这篇文章](https://course.rs/advance/concurrency-with-threads/sync2.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [运行期初始化](https://course.rs/advance/global-variable.html#运行期初始化)\n",
    "\n",
    "以上的静态初始化有一个致命的问题：无法用函数进行静态初始化，例如你如果想声明一个全局的`Mutex`锁："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot call non-const associated function `<String as From<&str>>::from` in statics",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0015] Error:\u001b[0m cannot call non-const associated function `<String as From<&str>>::from` in statics",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_8:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m2 │\u001b[0m \u001b[38;5;249ms\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mN\u001b[0m\u001b[38;5;249mA\u001b[0m\u001b[38;5;249mM\u001b[0m\u001b[38;5;249mE\u001b[0m\u001b[38;5;249mS\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mM\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mx\u001b[0m\u001b[38;5;249m<\u001b[0m\u001b[38;5;249mS\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mg\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mM\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mx\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mw\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;54mS\u001b[0m\u001b[38;5;54mt\u001b[0m\u001b[38;5;54mr\u001b[0m\u001b[38;5;54mi\u001b[0m\u001b[38;5;54mn\u001b[0m\u001b[38;5;54mg\u001b[0m\u001b[38;5;54m:\u001b[0m\u001b[38;5;54m:\u001b[0m\u001b[38;5;54mf\u001b[0m\u001b[38;5;54mr\u001b[0m\u001b[38;5;54mo\u001b[0m\u001b[38;5;54mm\u001b[0m\u001b[38;5;54m(\u001b[0m\u001b[38;5;54m\"\u001b[0m\u001b[38;5;54mS\u001b[0m\u001b[38;5;54mu\u001b[0m\u001b[38;5;54mn\u001b[0m\u001b[38;5;54mf\u001b[0m\u001b[38;5;54ma\u001b[0m\u001b[38;5;54mc\u001b[0m\u001b[38;5;54me\u001b[0m\u001b[38;5;54m,\u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54mJ\u001b[0m\u001b[38;5;54ma\u001b[0m\u001b[38;5;54mc\u001b[0m\u001b[38;5;54mk\u001b[0m\u001b[38;5;54m,\u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54mA\u001b[0m\u001b[38;5;54ml\u001b[0m\u001b[38;5;54ml\u001b[0m\u001b[38;5;54me\u001b[0m\u001b[38;5;54mn\u001b[0m\u001b[38;5;54m\"\u001b[0m\u001b[38;5;54m)\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                                          \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m                                                            \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m error: cannot call non-const associated function `<String as From<&str>>::from` in statics",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "use std::sync::Mutex;\n",
    "static NAMES: Mutex<String> = Mutex::new(String::from(\"Sunface, Jack, Allen\"));\n",
    "\n",
    "fn main() {\n",
    "    let v = NAMES.lock().unwrap();\n",
    "    println!(\"{}\",v);\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "但你又必须在声明时就对`NAMES`进行初始化，此时就陷入了两难的境地。好在天无绝人之路，我们可以使用`lazy_static`包来解决这个问题。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [lazy_static](https://course.rs/advance/global-variable.html#lazy_static)\n",
    "\n",
    "[`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs)是社区提供的非常强大的宏，用于懒初始化静态变量，之前的静态变量都是在编译期初始化的，因此无法使用函数调用进行赋值，而`lazy_static`允许我们在运行期初始化静态变量！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [],
   "source": [
    "use std::sync::Mutex;\n",
    "use lazy_static::lazy_static;\n",
    "\n",
    "lazy_static! {\n",
    "    static ref NAMES: Mutex<String> = Mutex::new(String::from(\"Sunface, Jack, Allen\"));\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let mut v = NAMES.lock().unwrap();\n",
    "    v.push_str(\", Myth\");\n",
    "    println!(\"{}\",v);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当然，使用`lazy_static`在每次访问静态变量时，会有轻微的性能损失，因为其内部实现用了一个底层的并发原语`std::sync::Once`，在每次访问该变量时，程序都会执行一次原子指令用于确认静态变量的初始化是否完成。\n",
    "\n",
    "`lazy_static`宏，匹配的是`static ref`，所以定义的静态变量都是不可变引用\n",
    "\n",
    "可能有读者会问，为何需要在运行期初始化一个静态变量，除了上面的全局锁，你会遇到最常见的场景就是：**一个全局的动态配置，它在程序开始后，才加载数据进行初始化，最终可以让各个线程直接访问使用**\n",
    "\n",
    "再来看一个使用`lazy_static`实现全局缓存的例子:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [],
   "source": [
    "use lazy_static::lazy_static;\n",
    "use std::collections::HashMap;\n",
    "\n",
    "lazy_static! {\n",
    "    static ref HASHMAP: HashMap<u32, &'static str> = {\n",
    "        let mut m = HashMap::new();\n",
    "        m.insert(0, \"foo\");\n",
    "        m.insert(1, \"bar\");\n",
    "        m.insert(2, \"baz\");\n",
    "        m\n",
    "    };\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    // 首次访问`HASHMAP`的同时对其进行初始化\n",
    "    println!(\"The entry for `0` is \\\"{}\\\".\", HASHMAP.get(&0).unwrap());\n",
    "\n",
    "    // 后续的访问仅仅获取值，再不会进行任何初始化操作\n",
    "    println!(\"The entry for `1` is \\\"{}\\\".\", HASHMAP.get(&1).unwrap());\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "需要注意的是，`lazy_static`直到运行到`main`中的第一行代码时，才进行初始化，非常`lazy static`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [Box::leak](https://course.rs/advance/global-variable.html#boxleak)\n",
    "\n",
    "在`Box`智能指针章节中，我们提到了`Box::leak`可以用于全局变量，例如用作运行期初始化的全局动态配置，先来看看如果不使用`lazy_static`也不使用`Box::leak`，会发生什么："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "temporary value dropped while borrowed",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0716] Error:\u001b[0m temporary value dropped while borrowed",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_9:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m10 │\u001b[0m \u001b[38;5;68m╭\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m▶\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68mC\u001b[0m\u001b[38;5;68mO\u001b[0m\u001b[38;5;68mN\u001b[0m\u001b[38;5;68mF\u001b[0m\u001b[38;5;68mI\u001b[0m\u001b[38;5;68mG\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m=\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68mS\u001b[0m\u001b[38;5;68mo\u001b[0m\u001b[38;5;68mm\u001b[0m\u001b[38;5;68me\u001b[0m\u001b[38;5;68m(\u001b[0m\u001b[38;5;68m&\u001b[0m\u001b[38;5;68mm\u001b[0m\u001b[38;5;68mu\u001b[0m\u001b[38;5;68mt\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;54mC\u001b[0m\u001b[38;5;54mo\u001b[0m\u001b[38;5;54mn\u001b[0m\u001b[38;5;54mf\u001b[0m\u001b[38;5;54mi\u001b[0m\u001b[38;5;54mg\u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m{\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;68m│\u001b[0m                                \u001b[38;5;54m▲\u001b[0m          ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;68m│\u001b[0m \u001b[38;5;54m╭\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m╯\u001b[0m          ",
      " \u001b[38;5;240m   ┆\u001b[0m \u001b[38;5;68m┆\u001b[0m \u001b[38;5;54m┆\u001b[0m   ",
      " \u001b[38;5;246m13 │\u001b[0m \u001b[38;5;68m│\u001b[0m \u001b[38;5;54m├\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m▶\u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;54m}\u001b[0m\u001b[38;5;68m)\u001b[0m\u001b[38;5;100m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;68m│\u001b[0m \u001b[38;5;54m│\u001b[0m            \u001b[38;5;68m▲\u001b[0m\u001b[38;5;100m┬\u001b[0m   ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;68m│\u001b[0m \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m creates a temporary value which is freed while still in use",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;68m│\u001b[0m              \u001b[38;5;68m│\u001b[0m\u001b[38;5;100m│\u001b[0m   ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m┴\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m assignment requires that borrow lasts for `'static`",
      " \u001b[38;5;240m   │\u001b[0m                 \u001b[38;5;100m│\u001b[0m   ",
      " \u001b[38;5;240m   │\u001b[0m                 \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m temporary value is freed at the end of this statement",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Config {\n",
    "    a: String,\n",
    "    b: String,\n",
    "}\n",
    "static mut CONFIG: Option<&mut Config> = None;\n",
    "\n",
    "fn main() {\n",
    "    unsafe {\n",
    "        CONFIG = Some(&mut Config {\n",
    "            a: \"A\".to_string(),\n",
    "            b: \"B\".to_string(),\n",
    "        });\n",
    "\n",
    "        println!(\"{:?}\", CONFIG)\n",
    "    }\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以上代码我们声明了一个全局动态配置`CONFIG`，并且其值初始化为`None`，然后在程序开始运行后，给它赋予相应的值，运行后报错:\n",
    "\n",
    "可以看到，Rust 的借用和生命周期规则限制了我们做到这一点，因为试图将一个局部生命周期的变量赋值给全局生命周期的`CONFIG`，这明显是不安全的。\n",
    "\n",
    "好在`Rust`为我们提供了`Box::leak`方法，它可以将一个变量从内存中泄漏(听上去怪怪的，竟然做主动内存泄漏)，然后将其变为`'static`生命周期，最终该变量将和程序活得一样久，因此可以赋值给全局静态变量`CONFIG`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "creating a shared reference to mutable static",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[static_mut_refs] Error:\u001b[0m creating a shared reference to mutable static",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_11:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m17 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m!\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m{\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m?\u001b[0m\u001b[38;5;249m}\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mC\u001b[0m\u001b[38;5;54mO\u001b[0m\u001b[38;5;54mN\u001b[0m\u001b[38;5;54mF\u001b[0m\u001b[38;5;54mI\u001b[0m\u001b[38;5;54mG\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m                          \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m                             \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m shared reference to mutable static",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Config {\n",
    "    a: String,\n",
    "    b: String\n",
    "}\n",
    "static mut CONFIG: Option<&mut Config> = None;\n",
    "\n",
    "fn main() {\n",
    "    let c = Box::new(Config {\n",
    "        a: \"A\".to_string(),\n",
    "        b: \"B\".to_string(),\n",
    "    });\n",
    "\n",
    "    unsafe {\n",
    "        // 将`c`从内存中泄漏，变成`'static`生命周期\n",
    "        CONFIG = Some(Box::leak(c));\n",
    "        println!(\"{:?}\", CONFIG);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [从函数中返回全局变量](https://course.rs/advance/global-variable.html#从函数中返回全局变量)\n",
    "\n",
    "问题又来了，如果我们需要在运行期，从一个函数返回一个全局变量该如何做？例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot return value referencing temporary value",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0515] Error:\u001b[0m cannot return value referencing temporary value",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_12:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m 9 │\u001b[0m \u001b[38;5;54m╭\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m▶\u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mS\u001b[0m\u001b[38;5;54mo\u001b[0m\u001b[38;5;54mm\u001b[0m\u001b[38;5;54me\u001b[0m\u001b[38;5;54m(\u001b[0m\u001b[38;5;54m&\u001b[0m\u001b[38;5;54mm\u001b[0m\u001b[38;5;54mu\u001b[0m\u001b[38;5;54mt\u001b[0m\u001b[38;5;54m \u001b[0m\u001b[38;5;100mC\u001b[0m\u001b[38;5;100mo\u001b[0m\u001b[38;5;100mn\u001b[0m\u001b[38;5;100mf\u001b[0m\u001b[38;5;100mi\u001b[0m\u001b[38;5;100mg\u001b[0m\u001b[38;5;100m \u001b[0m\u001b[38;5;100m{\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;54m│\u001b[0m                   \u001b[38;5;100m▲\u001b[0m          ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;54m│\u001b[0m \u001b[38;5;100m╭\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m╯\u001b[0m          ",
      " \u001b[38;5;240m   ┆\u001b[0m \u001b[38;5;54m┆\u001b[0m \u001b[38;5;100m┆\u001b[0m   ",
      " \u001b[38;5;246m12 │\u001b[0m \u001b[38;5;54m│\u001b[0m \u001b[38;5;100m├\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m▶\u001b[0m\u001b[38;5;100m \u001b[0m\u001b[38;5;100m \u001b[0m\u001b[38;5;100m \u001b[0m\u001b[38;5;100m \u001b[0m\u001b[38;5;100m \u001b[0m\u001b[38;5;100m}\u001b[0m\u001b[38;5;54m)\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;54m│\u001b[0m \u001b[38;5;100m│\u001b[0m        \u001b[38;5;54m▲\u001b[0m   ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;54m│\u001b[0m \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m temporary value created here",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;54m│\u001b[0m          \u001b[38;5;54m│\u001b[0m   ",
      " \u001b[38;5;240m   │\u001b[0m \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┴\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m returns a value referencing data owned by the current function",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Config {\n",
    "    a: String,\n",
    "    b: String,\n",
    "}\n",
    "static mut CONFIG: Option<&mut Config> = None;\n",
    "\n",
    "fn init() -> Option<&'static mut Config> {\n",
    "    Some(&mut Config {\n",
    "        a: \"A\".to_string(),\n",
    "        b: \"B\".to_string(),\n",
    "    })\n",
    "}\n",
    "\n",
    "\n",
    "fn main() {\n",
    "    unsafe {\n",
    "        CONFIG = init();\n",
    "\n",
    "        println!(\"{:?}\", CONFIG)\n",
    "    }\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "报错这里就不展示了，跟之前大同小异，还是生命周期引起的，那么该如何解决呢？依然可以用`Box::leak`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "creating a shared reference to mutable static",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[static_mut_refs] Error:\u001b[0m creating a shared reference to mutable static",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_2:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m22 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m!\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m{\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m?\u001b[0m\u001b[38;5;249m}\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mC\u001b[0m\u001b[38;5;54mO\u001b[0m\u001b[38;5;54mN\u001b[0m\u001b[38;5;54mF\u001b[0m\u001b[38;5;54mI\u001b[0m\u001b[38;5;54mG\u001b[0m\u001b[38;5;249m)\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m                          \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m                             \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m shared reference to mutable static",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Config {\n",
    "    a: String,\n",
    "    b: String,\n",
    "}\n",
    "static mut CONFIG: Option<&mut Config> = None;\n",
    "\n",
    "fn init() -> Option<&'static mut Config> {\n",
    "    let c = Box::new(Config {\n",
    "        a: \"A\".to_string(),\n",
    "        b: \"B\".to_string(),\n",
    "    });\n",
    "\n",
    "    Some(Box::leak(c))\n",
    "}\n",
    "\n",
    "\n",
    "fn main() {\n",
    "    unsafe {\n",
    "        CONFIG = init();\n",
    "\n",
    "        println!(\"{:?}\", CONFIG)\n",
    "    }\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [标准库中的 Once 和 Lazy](https://course.rs/advance/global-variable.html#标准库中的-once-和-lazy)\n",
    "\n",
    "在 Rust 1.70.0 版本之前，标准库通过实验性 API 提供 `lazy::OnceCell` 和 `lazy::SyncOnceCell` 来实现单次初始化容器，这时，懒初始化主要依靠 `lazy_static` 。 随着 `cell::OnceCell` 和 `sync::OnceLock` 在 1.70.0 中稳定和 `LazyCell` 和 `LazyLock` 在 1.80.0 中稳定，只使用标准库实现懒加载成为可能。\n",
    "\n",
    "这4个容器可以这样区分：\n",
    "\n",
    "|      | 单线程   | 多线程   |\n",
    "| ---- | -------- | -------- |\n",
    "| Once | OnceCell | OnceLock |\n",
    "| Lazy | LazyCell | LazyLock |\n",
    "\n",
    "其中，`Lazy` 会自动按需加载内容，让代码更简洁，更人性化，而 `Once` 则可以手动指定初始化的时机或使用不同的方法初始化，更强大。 `Cell` 的实现更简单，效率也更高，但是他并不保证线程安全，而 `Lock` 通过内部同步机制实现了线程安全。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "rustc 1.90.0 (1159e78c4 2025-09-14)\n"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "! rustc -V"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [Once 使用方法](https://course.rs/advance/global-variable.html#once-使用方法)\n",
    "\n",
    "下面，我们先看一下 `Once` 的使用方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [],
   "source": [
    "use std::{sync::OnceLock, thread};\n",
    "\n",
    "fn main() {\n",
    "    // 子线程中调用\n",
    "    let handle = thread::spawn(|| {\n",
    "        let logger = Logger::global();\n",
    "        logger.log(\"thread message\".to_string());\n",
    "    });\n",
    "\n",
    "    // 主线程调用\n",
    "    let logger = Logger::global();\n",
    "    logger.log(\"some message\".to_string());\n",
    "\n",
    "    let logger2 = Logger::global();\n",
    "    logger2.log(\"other message\".to_string());\n",
    "\n",
    "    handle.join().unwrap();\n",
    "}\n",
    "\n",
    "#[derive(Debug)]\n",
    "struct Logger;\n",
    "\n",
    "static LOGGER: OnceLock<Logger> = OnceLock::new();\n",
    "\n",
    "impl Logger {\n",
    "    fn global() -> &'static Logger {\n",
    "        // 获取或初始化 Logger\n",
    "        LOGGER.get_or_init(|| {\n",
    "            println!(\"Logger is being created...\"); // 初始化打印\n",
    "            Logger\n",
    "        })\n",
    "    }\n",
    "\n",
    "    fn log(&self, message: String) {\n",
    "        println!(\"{}\", message)\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以上代码我们声明了一个 `global()` 关联函数，并在其内部调用 `get_or_init` 进行初始化 `Logger`，之后在不同线程上多次调用 `Logger::global()` 获取其实例。 由于需要在多个线程中使用，所以我们使用了 `OnceLock`。以下是输出："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Logger is being created...\n",
      "some message\n",
      "thread message\n",
      "other message\n"
     ]
    }
   ],
   "source": [
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，`Logger is being created...` 在多个线程中使用也只被打印了一次。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [Lazy 使用方法](https://course.rs/advance/global-variable.html#lazy-使用方法)\n",
    "\n",
    "上述例子如果使用 `LazyLock` 来实现，则可以变得更加简洁："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "vscode": {
     "languageId": "rust"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Logger is being created...\n",
      "some message\n",
      "thread message\n",
      "other message\n"
     ]
    }
   ],
   "source": [
    "use std::{sync::LazyLock, thread};\n",
    "\n",
    "fn main() {\n",
    "    // 子线程中调用\n",
    "    let handle = thread::spawn(|| {\n",
    "        let logger = &LOGGER;\n",
    "        logger.log(\"thread message\".to_string());\n",
    "    });\n",
    "\n",
    "    // 主线程调用\n",
    "    let logger = &LOGGER;\n",
    "    logger.log(\"some message\".to_string());\n",
    "\n",
    "    let logger2 = &LOGGER;\n",
    "    logger2.log(\"other message\".to_string());\n",
    "\n",
    "    handle.join().unwrap();\n",
    "}\n",
    "\n",
    "#[derive(Debug)]\n",
    "struct Logger;\n",
    "\n",
    "static LOGGER: LazyLock<Logger> = LazyLock::new(Logger::new);\n",
    "\n",
    "impl Logger {\n",
    "    fn new() -> Logger {\n",
    "        println!(\"Logger is being created...\");\n",
    "        Logger\n",
    "    }\n",
    "\n",
    "    fn log(&self, message: String) {\n",
    "        println!(\"{}\", message)\n",
    "    }\n",
    "}\n",
    "\n",
    "main();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以上代码中，我们使用 `LazyLock::new` 方法直接对全局变量 `LOGGER` 进行赋值，并传入一个初始化函数。 使用的时候，可以直接使用对全局变量的引用。在获取引用的时候， `LazyLock` 会自动检查初始化的状态并进行初始化。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# [总结](https://course.rs/advance/global-variable.html#总结)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在 Rust 中有很多方式可以创建一个全局变量，本章也只是介绍了其中一部分，更多的还等待大家自己去挖掘学习(当然，未来可能本章节会不断完善，最后变成一个巨无霸- , -)。\n",
    "\n",
    "简单来说，全局变量可以分为两种：\n",
    "\n",
    "- 编译期初始化的全局变量，`const`创建常量，`static`创建静态变量，`Atomic`创建原子类型\n",
    "- 运行期初始化的全局变量，`lazy_static`用于懒初始化，`Box::leak`利用内存泄漏将一个变量的生命周期变为`'static`"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Rust",
   "language": "rust",
   "name": "rust"
  },
  "language_info": {
   "codemirror_mode": "rust",
   "file_extension": ".rs",
   "mimetype": "text/rust",
   "name": "Rust",
   "pygment_lexer": "rust",
   "version": ""
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
